/*
 * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

use crate::externs::*;
use crate::initramfs::*;

// static DOC: &str = "GNU `cpio' copies files to and from archives\n\
// \n\
// Examples:\n\
//  # Copy files named in name-list to the archive\n\
//  cpio -o < name-list [> archive]\n\
//  # Extract files from the archive\n\
//  cpio -i [< archive]\n\
//  # Copy files named in name-list to destination-directory\n\
//  cpio -p destination-directory < name-list\n";

use std::fs::File;
use std::io;
use std::sync::MutexGuard;
use std::sync::{Mutex, OnceLock};

pub static ARCHIVE_DES: OnceLock<Mutex<File>> = OnceLock::new();

pub fn get_archive_des() -> io::Result<MutexGuard<'static, File>> {
    let mutex = ARCHIVE_DES
        .get()
        .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "ARCHIVE_DES not initialized"))?;
    mutex.lock().map_err(|e| {
        io::Error::new(
            io::ErrorKind::Other,
            format!("Failed to lock ARCHIVE_DES: {}", e),
        )
    })
}

// 设置 archive_des
pub fn set_archive_des(value: File) -> io::Result<()> {
    // 如果 ARCHIVE_DES 未初始化，先初始化
    if ARCHIVE_DES.get().is_none() {
        ARCHIVE_DES
            .set(Mutex::new(value))
            .map_err(|_| io::Error::new(io::ErrorKind::Other, "ARCHIVE_DES already initialized"))?;
        Ok(())
    } else {
        // 如果已初始化，获取锁并设置
        let mutex = ARCHIVE_DES.get().ok_or_else(|| {
            io::Error::new(io::ErrorKind::NotFound, "ARCHIVE_DES not found")
        })?;
        let mut guard = mutex.lock().map_err(|e| {
            io::Error::new(
                io::ErrorKind::Other,
                format!("Failed to lock ARCHIVE_DES: {}", e),
            )
        })?;
        *guard = value;
        Ok(())
    }
}

pub struct AppArgs {
    // Operation modifiers valid in copy-out and copy-pass modes GRID 600
    name_end: i8,
    reset_time_flag: bool,
    append_flag: bool,
    swap_bytes_flag: bool,
    swap_halfwords_flag: bool,
    io_block_size: i32,
    archive_format: ArchiveFormat,
    create_dir_flag: bool,
    change_directory_option: Option<String>,
    metadata_type: MetadataTypes,
    pattern_file_name: Option<String>,
    archive_name: Option<String>,
    copy_matching_files: bool,
    copy_function: Option<CopyFunctionFn>,
    input_archive_name: Option<String>,
    link_flag: bool,
    //xstat: Option<Xstat>,
    retain_time_flag: bool,
    new_media_message: Option<String>,
    new_media_message_with_number: Option<String>,
    new_media_message_after_number: Option<String>,

    crc_i_flag: bool,
    crc: usize,

    rename_batch_file: Option<String>,

    no_abs_paths_flag: bool,
    rename_flag: bool,

    set_owner_flag: bool,
    set_group_flag: bool,
    set_owner: u32,
    set_group: u32,

    output_archive_name: Option<String>,
    only_verify_crc_flag: bool,
    ignore_devno_option: bool,
    renumber_inodes_option: bool,
    rsh_command_option: Option<String>,
    quiet_flag: bool,

    ignore_dirnlink_option: bool,

    no_chown_flag: bool,
    table_flag: bool,
    unconditional_flag: bool,
    verbose_flag: bool,
    dot_flag: bool,
    warn_option: i32,
    sparse_flag: bool,
    force_local_option: bool,
    to_stdout_option: bool,
    // debug_flag: bool,
    numeric_uid: bool,

    directory_name: Option<String>,
    num_patterns: i32,
    save_patterns: Vec<String>,
}
impl AppArgs {
    pub fn new() -> Self {
        AppArgs {
            name_end: b'\n' as i8,
            reset_time_flag: false,
            append_flag: false,
            swap_bytes_flag: false,
            swap_halfwords_flag: false,
            io_block_size: 512,
            archive_format: ArchiveFormat::Unknown,
            create_dir_flag: false,
            change_directory_option: None,
            metadata_type: MetadataTypes::TypeNone,
            pattern_file_name: None,
            archive_name: None,
            copy_matching_files: true,
            copy_function: None,
            input_archive_name: None,
            link_flag: false,
            //            xstat: None,
            retain_time_flag: false,
            new_media_message: None,
            new_media_message_with_number: None,
            new_media_message_after_number: None,
            crc_i_flag: false,
            crc: 0,
            rename_batch_file: None,
            no_abs_paths_flag: false,
            rename_flag: false,
            set_owner_flag: false,
            set_group_flag: false,
            set_owner: 0,
            set_group: 0,
            output_archive_name: None,
            only_verify_crc_flag: false,
            ignore_devno_option: false,
            renumber_inodes_option: false,
            rsh_command_option: None,
            quiet_flag: false,
            ignore_dirnlink_option: false,
            no_chown_flag: false,
            table_flag: false,
            unconditional_flag: false,
            verbose_flag: false,
            dot_flag: false,
            warn_option: 0,
            sparse_flag: false,
            force_local_option: false,
            to_stdout_option: false,
            //            debug_flag: false,
            numeric_uid: false,
            directory_name: None,
            //            archive_des: 0,
            num_patterns: 0,
            save_patterns: vec![],
        }
    }
}

pub static APPARGS: OnceLock<Mutex<AppArgs>> = OnceLock::new();

pub fn get_save_patterns() -> Vec<String> {
    APPARGS.get().unwrap().lock().unwrap().save_patterns.clone()
}
pub fn set_save_patterns(value: Vec<String>) {
    APPARGS.get().unwrap().lock().unwrap().save_patterns = value;
}

pub fn get_num_patterns() -> i32 {
    APPARGS.get().unwrap().lock().unwrap().num_patterns
}
pub fn set_num_patterns(value: i32) {
    if let Some(appargs) = APPARGS.get() {
        if let Ok(mut guard) = appargs.lock() {
            guard.num_patterns = value;
        } else {
            eprintln!("Failed to lock APPARGS");
            // 处理锁获取失败的情况
        }
    } else {
        eprintln!("APPARGS is not initialized");
        // 处理 APPARGS 未初始化的情况
    }
}
pub fn set_directory_name(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().directory_name = value;
}
pub fn get_directory_name() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .directory_name
        .clone()
}

pub fn get_crc() -> usize {
    APPARGS.get().unwrap().lock().unwrap().crc
}
pub fn set_crc(value: usize) {
    APPARGS.get().unwrap().lock().unwrap().crc = value;
}
pub fn get_crc_i_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().crc_i_flag
}
pub fn set_crc_i_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().crc_i_flag = value;
}

pub fn get_name_end() -> i8 {
    APPARGS.get().unwrap().lock().unwrap().name_end
}

pub fn set_name_end(value: i8) {
    APPARGS.get().unwrap().lock().unwrap().name_end = value;
}

pub fn get_reset_time_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().reset_time_flag
}

pub fn set_reset_time_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().reset_time_flag = value;
}

pub fn get_append_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().append_flag
}

pub fn set_append_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().append_flag = value;
}

pub fn get_swap_bytes_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().swap_bytes_flag
}

pub fn set_swap_bytes_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().swap_bytes_flag = value;
}

pub fn get_swap_halfwords_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().swap_halfwords_flag
}

pub fn set_swap_halfwords_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().swap_halfwords_flag = value;
}

pub fn get_io_block_size() -> i32 {
    APPARGS.get().unwrap().lock().unwrap().io_block_size
}

pub fn set_io_block_size(value: i32) {
    APPARGS.get().unwrap().lock().unwrap().io_block_size = value;
}

pub fn get_archive_format() -> ArchiveFormat {
    APPARGS.get().unwrap().lock().unwrap().archive_format
}

pub fn set_archive_format(value: ArchiveFormat) {
    APPARGS.get().unwrap().lock().unwrap().archive_format = value;
}

pub fn get_create_dir_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().create_dir_flag
}

pub fn set_create_dir_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().create_dir_flag = value;
}

pub fn get_change_directory_option() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .change_directory_option
        .clone()
}

pub fn set_change_directory_option(value: Option<String>) {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .change_directory_option = value;
}

pub fn get_metadata_type() -> MetadataTypes {
    APPARGS.get().unwrap().lock().unwrap().metadata_type
}

pub fn set_metadata_type(value: MetadataTypes) {
    APPARGS.get().unwrap().lock().unwrap().metadata_type = value;
}

pub fn get_pattern_file_name() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .pattern_file_name
        .clone()
}

pub fn set_pattern_file_name(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().pattern_file_name = value;
}

pub fn get_archive_name() -> Option<String> {
    APPARGS.get().unwrap().lock().unwrap().archive_name.clone()
}

pub fn set_archive_name(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().archive_name = value;
}

pub fn get_copy_matching_files() -> bool {
    APPARGS.get().unwrap().lock().unwrap().copy_matching_files
}

pub fn set_copy_matching_files(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().copy_matching_files = value;
}

pub fn get_copy_function() -> Option<CopyFunctionFn> {
    APPARGS.get().unwrap().lock().unwrap().copy_function
}

pub fn set_copy_function(value: CopyFunctionFn) {
    APPARGS.get().unwrap().lock().unwrap().copy_function = Some(value);
}

pub fn get_input_archive_name() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .input_archive_name
        .clone()
}

pub fn set_input_archive_name(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().input_archive_name = value;
}

pub fn get_link_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().link_flag
}

pub fn set_link_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().link_flag = value;
}

// pub fn get_xstat() -> Xstat {
//      APPARGS.get().unwrap().lock().unwrap().xstat.unwrap()
// }

// pub fn set_xstat(value: Xstat) {
//     APPARGS.get().unwrap().lock().unwrap().xstat.unwrap() = value;
// }

pub fn get_retain_time_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().retain_time_flag
}

pub fn set_retain_time_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().retain_time_flag = value;
}

pub fn get_new_media_message() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .new_media_message
        .clone()
}

pub fn set_args_new_media_message(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().new_media_message = value;
}

pub fn get_args_new_media_message_with_number() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .new_media_message_with_number
        .clone()
}

pub fn set_new_media_message_with_number(value: Option<String>) {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .new_media_message_with_number = value;
}

pub fn get_new_media_message_after_number() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .new_media_message_after_number
        .clone()
}

pub fn set_new_media_message_after_number(value: Option<String>) {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .new_media_message_after_number = value;
}

pub fn get_set_owner_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().set_owner_flag
}

pub fn set_set_owner_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().set_owner_flag = value;
}

pub fn get_set_group_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().set_group_flag
}

pub fn set_set_group_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().set_group_flag = value;
}

pub fn get_set_owner() -> u32 {
    APPARGS.get().unwrap().lock().unwrap().set_owner
}

pub fn set_set_owner(value: u32) {
    APPARGS.get().unwrap().lock().unwrap().set_owner = value;
}

pub fn get_set_group() -> u32 {
    APPARGS.get().unwrap().lock().unwrap().set_group
}

pub fn set_set_group(value: u32) {
    APPARGS.get().unwrap().lock().unwrap().set_group = value;
}

pub fn get_output_archive_name() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .output_archive_name
        .clone()
}
pub fn get_sparse_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().sparse_flag
}

pub fn get_rsh_command_option() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .rsh_command_option
        .clone()
}

pub fn set_output_archive_name(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().output_archive_name = value;
}

pub fn get_only_verify_crc_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().only_verify_crc_flag
}

pub fn set_only_verify_crc_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().only_verify_crc_flag = value;
}

pub fn get_ignore_devno_option() -> bool {
    APPARGS.get().unwrap().lock().unwrap().ignore_devno_option
}

pub fn set_ignore_devno_option(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().ignore_devno_option = value;
}

pub fn get_renumber_inodes_option() -> bool {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .renumber_inodes_option
}

pub fn set_renumber_inodes_option(value: bool) {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .renumber_inodes_option = value;
}


pub fn set_rsh_command_option(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().rsh_command_option = value;
}

pub fn get_quiet_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().quiet_flag
}

pub fn set_quiet_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().quiet_flag = value;
}

pub fn get_no_chown_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().no_chown_flag
}

pub fn set_no_chown_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().no_chown_flag = value;
}

pub fn get_table_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().table_flag
}

pub fn set_table_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().table_flag = value;
}

pub fn get_unconditional_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().unconditional_flag
}

pub fn set_unconditional_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().unconditional_flag = value;
}

pub fn get_verbose_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().verbose_flag
}

pub fn set_verbose_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().verbose_flag = value;
}

pub fn get_dot_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().dot_flag
}

pub fn set_dot_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().dot_flag = value;
}

pub fn get_warn_option() -> i32 {
    APPARGS.get().unwrap().lock().unwrap().warn_option
}

pub fn set_warn_option(value: i32) {
    APPARGS.get().unwrap().lock().unwrap().warn_option = value;
}



pub fn set_sparse_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().sparse_flag = value;
}
#[allow(dead_code)]
pub fn get_force_local_option() -> bool {
    APPARGS.get().unwrap().lock().unwrap().force_local_option
}

pub fn set_force_local_option(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().force_local_option = value;
}

pub fn get_to_stdout_option() -> bool {
    APPARGS.get().unwrap().lock().unwrap().to_stdout_option
}

pub fn set_to_stdout_option(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().to_stdout_option = value;
}

// pub fn get_debug_flag() -> bool {
//     APPARGS.get().unwrap().lock().unwrap().debug_flag
// }

// pub fn set_debug_flag(value: bool) {
//     APPARGS.get().unwrap().lock().unwrap().debug_flag = value;
// }

pub fn get_numeric_uid() -> bool {
    APPARGS.get().unwrap().lock().unwrap().numeric_uid
}

pub fn set_numeric_uid(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().numeric_uid = value;
}

pub fn set_no_abs_paths_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().no_abs_paths_flag = value;
}
pub fn get_no_abs_paths_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().no_abs_paths_flag
}

pub fn set_ignore_dirnlink_option(value: bool) {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .ignore_dirnlink_option = value;
}
pub fn get_ignore_dirnlink_option() -> bool {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .ignore_dirnlink_option
}

pub fn set_rename_flag(value: bool) {
    APPARGS.get().unwrap().lock().unwrap().rename_flag = value;
}
pub fn get_rename_flag() -> bool {
    APPARGS.get().unwrap().lock().unwrap().rename_flag
}
pub fn set_rename_batch_file(value: Option<String>) {
    APPARGS.get().unwrap().lock().unwrap().rename_batch_file = value;
}
pub fn get_rename_batch_file() -> Option<String> {
    APPARGS
        .get()
        .unwrap()
        .lock()
        .unwrap()
        .rename_batch_file
        .clone()
}

